/*
* js中每个函数都是Function类型的实例,都具有属性和方法
* */

{
  /*创建function的两种方式
  * 函数声明: 解析器会优先读取所有函数声明,也就是,函数声明不用等到运行过,才开始就可以直接调用
  * 函数表达式: 解析器执行到它的位置,才会被解释执行,就是只有运行过function之后,这个function才会被调用
  * 以上是2者区别,其他都一样
  * */
  console.log('--------------------创建函数的两种方式--------------------')
  console.log(sum1(10, 10))
  function sum1(a, b) {
    return a + b
  }

  const sum2 = function (a, b) {
    return a + b
  }
  // 函数表达式的ES6写法
  const sum2ByES6 = (a, b) => {
    return a + b
  }

  /*
  * 函数名只是指向函数的指针,所有一个函数可以有多个函数名
  * 函数名直接赋值,表示访问函数的指针,而不是调用函数,赋值之后,将原先函数名设置null,对新赋值的函数的运算没有影响,因为设置null的只是一个指针
  * 以下是demo说明
  * */
  const copySum = sum1
  sum1 = null
  console.log(copySum(1, 2))

  /*
  * 由于函数名只是一个指针,所以函数没有重载,第二次的addNum只是对第一次addNum的覆盖
  * */
  function addNum(num) {
    return 100 + num
  }
  function addNum(num) {
    return 200 + num
  }
  console.log(addNum(100)) // 300
}

{
  console.log('--------------------作为值的函数--------------------')

  const persons = [
    {name: 'zhangsan1', age: 14},
    {name: 'zhangsan2', age: 23},
    {name: 'zhangsan3', age: 18},
    {name: 'zhangsan4', age: 24},
    {name: 'zhangsan5', age: 35},
    {name: 'zhangsan6', age: 16}

  ]
  function comparisonFunction(paramName) {
    const comparison = function (obj1, obj2) {
      if (obj1[paramName] < obj2[paramName]) {
        return -1
      } else if (obj1[paramName] > obj2[paramName]) {
        return 1
      } else {
        return 0
      }
    }
    return comparison
  }
  const newPersons = persons.sort(comparisonFunction('age'))
  console.log(newPersons)
}

{
  console.log('--------------------函数内部属性--------------------')
  /*
  * arguments: 包含传入函数中所有参数,是一个数组
  * callee: 是一个指针,指向arguments对象的函数
  * demo,阶乘,用callee进行解耦
  * */
  function factorial1(num) {
    if (num <= 1) {
      return 1
    } else {
      return num * factorial1(num - 1)
    }
  }
  console.log(factorial1(3))

  function factorial2(num) {
    if (num <= 1) {
      return 1
    } else {
      return num * arguments.callee(num - 1)
    }
  }
  console.log(factorial2(3))
}

{
  console.log('--------------------函数属性和方法 apply(),call(),bind()--------------------')
}
